package com.dbflow5.query;

import com.dbflow5.annotation.Collate;
import com.dbflow5.query.property.IProperty;
import com.dbflow5.sql.Query;

/**
 * Description: Class that represents a SQL order-by.
 */
public class OrderBy implements Query {
    public static final String ASCENDING = "ASC";
    public static final String DESCENDING = "DESC";

    private Collate collation = null;
    private String orderByString;

    private NameAlias column = null;
    /**
     * If true, append ASC, if false append DESC, or if null, then don't append.
     */
    private boolean isAscending = true;

    public OrderBy(NameAlias column, boolean isAscending){
        this.column = column;
        this.isAscending = isAscending;

        this.orderByString = null;
    }

    @Override
    public String getQuery() {
        String locOrderByString = orderByString;
        if (locOrderByString == null) {
            StringBuilder query = new StringBuilder()
                    .append(column)
                    .append(" ");
            if (collation != null) {
                query.append("COLLATE ").append(collation).append(" ");
            }
            query.append(isAscending? ASCENDING : DESCENDING);
            return query.toString();
        } else {
            return locOrderByString;
        }
    }

    public OrderBy(IProperty<?> property) {
        this(property.nameAlias(), true);
    }

    public OrderBy(String orderByString) {
        this(null, true);
        this.orderByString = orderByString;
    }

    public OrderBy ascending() {
        isAscending = true;
        return this;
    }

    public OrderBy descending() {
        isAscending = false;
        return this;
    }

    public OrderBy collate(Collate collate) {
        this.collation = collate;
        return this;
    }

    @Override
    public String toString() {
        return getQuery();
    }

    public static OrderBy fromProperty(IProperty<?> property, boolean isAscending) {
        return new OrderBy(property.nameAlias(),
                // if we use RANDOM(), leave out ascending qualifier as its not valid SQLite.
                property.equals(Method.random()) || isAscending);
    }

    public static OrderBy fromNameAlias(NameAlias nameAlias, boolean isAscending) {
        return new OrderBy(nameAlias, isAscending);
    }

    /**
     * Starts an [OrderBy] with RANDOM() query.
     * @return this
     */
    public OrderBy random() {
        return new OrderBy(Method.random().nameAlias(), true);
    }

    public static OrderBy fromString(String orderByString) {
        return new OrderBy(orderByString);
    }
}